package utility;

public class Support{

// Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
//   This program is free software; you can redistribute it and/or modify
//   it under the terms of the GNU General Public License as published by
//   the Free Software Foundation; either version 2, or (at your option)
//   any later version.
//
//   This program is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU General Public License for more details.
//***********************************************************************/
//

//  This module contains replacements for functions which are not
//  available on all platforms.  Where the functions are available
//  natively, these are (mostly) just wrappers.
//
//  Notice the function names here are prefixed by, eg, "my".  An
//  alternative would be to use the "standard" function name, and
//  provide the implementation only if required.  However the method
//  here has some advantages:
//  
//   - We can provide definite prototypes in support.h, rather than
//   worrying about whether a system prototype exists, and if so where,
//   and whether it is correct.  (Note that whether or not configure
//   finds a function and defines HAVE_FOO does not necessarily say
//   whether or not there is a _prototype_ for the function available.)
//
//   - We don't have to include config.h in support.h, but can instead
//   restrict it to this .c file.
//
//   - We can add some extra stuff to these functions if we want.
//
//  The main disadvantage is remembering to use these "my" functions on
//  systems which have the functions natively.
//
//**********************************************************************/
//
//#ifdef HAVE_CONFIG_H
//#include <config.h>
//#endif
//
//#include <assert.h>
//#include <ctype.h>
//#include <errno.h>
//#include <stdarg.h>
//#include <stdio.h>
//#include <stdlib.h>
//#include <string.h>
//#include <sys/stat.h>
//
//#ifdef GENERATING_MAC
//#include <events.h>		/* for WaitNextEvent() */
//#endif
//#ifdef HAVE_FCNTL_H
//#include <fcntl.h>
//#endif
//#ifdef HAVE_SYS_IOCTL_H
//#include <sys/ioctl.h>
//#endif
//#ifdef HAVE_SYS_SELECT_H
//#include <sys/select.h>
//#endif
//#ifdef HAVE_SYS_TIME_H
//#include <sys/time.h>
//#endif
//#ifdef HAVE_SYS_TYPES_H
//#include <sys/types.h>
//#endif
//#ifdef HAVE_UNISTD_H
//#include <unistd.h>		/* usleep, fcntl, gethostname */
//#endif
//#ifdef WIN32_NATIVE
//#include <process.h>
//#include <windows.h>
//#endif
//#ifdef HAVE_WINSOCK
//#include <winsock.h>
//#endif
//
//#include "fcintl.h"
//#include "mem.h"
//#include "netintf.h"
//
//#include "support.h"
//
///***************************************************************
//  Compare strings like strcmp(), but ignoring case.
//***************************************************************/
//int mystrcasecmp(final String str0, final String str1)
//{
//#ifdef HAVE_STRCASECMP
//  return strcasecmp (str0, str1);
//#else
//  for (; my_tolower(*str0) == my_tolower(*str1); str0++, str1++) {
//    if (*str0 == '\0') {
//      return 0;
//    }
//  }
//
//  return ((int) (unsigned char) my_tolower(*str0))
//    - ((int) (unsigned char) my_tolower(*str1));
//#endif
//}
//
///***************************************************************
//  Compare strings like strncmp(), but ignoring case.
//  ie, only compares first n chars.
//***************************************************************/
//int mystrncasecmp(final String str0, final String str1, size_t n)
//{
//#ifdef HAVE_STRNCASECMP
//  return strncasecmp (str0, str1, n);
//#else
//  size_t i;
//  
//  for (i = 0; i < n && my_tolower(*str0) == my_tolower(*str1);
//       i++, str0++, str1++) {
//    if (*str0 == '\0') {
//      return 0;
//    }
//  }
//
//  if (i == n)
//    return 0;
//  else
//    return ((int) (unsigned char) my_tolower(*str0))
//      - ((int) (unsigned char) my_tolower(*str1));
//#endif
//}
//
//
///***************************************************************
//  Return a string which describes a given error (errno-style.)
//***************************************************************/
//final String mystrerror()
//{
//#ifdef WIN32_NATIVE
//  static char buf[256];
//  long int error;
//
//  error = GetLastError();
//  if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
//		     null, error, 0, buf, sizeof(buf), null)) {
//    buf = util.my_snprintf(
//		"error %ld (failed FormatMessage)", error);
//  }
//  return buf;
//#else
//#ifdef HAVE_STRERROR
//  return strerror(errno);
//#else
//  static char buf[64];
//
//  buf = util.my_snprintf(
//	      "error %d (compiled without strerror)", errno);
//  return buf;
//#endif
//#endif
//}
//
//
///***************************************************************
//  Suspend execution for the specified number of microseconds.
//***************************************************************/
//void myusleep(unsigned long usec)
//{
//#ifdef HAVE_USLEEP
//  usleep(usec);
//#else
//#ifdef HAVE_SNOOZE		/* BeOS */
//  snooze(usec);
//#else
//#ifdef GENERATING_MAC
//  EventRecord the_event;	/* dummy - always be a null event */
//  usec /= 16666;		/* microseconds to 1/60th seconds */
//  if (usec < 1) usec = 1;
//  /* suposed to give other application processor time for the mac */
//  WaitNextEvent(0, &the_event, usec, 0L);
//#else
//#ifdef WIN32_NATIVE
//  Sleep(usec / 1000);
//#else
//  struct timeval tv;
//  tv.tv_sec=0;
//  tv.tv_usec=usec;
//  /* FIXME: an interrupt can cause an EINTR return here.  In that case we
//   * need to have another select call. */
//  select(0, null, null, null, &tv);
//#endif
//#endif
//#endif
//#endif
//}
//
//
///**********************************************************************
// mystrlcpy() and mystrlcat() provide (non-standard) functions
// strlcpy() and strlcat(), with semantics following OpenBSD (and
// maybe others).  They are intended as more user-friendly
// versions of strncpy and strncat, in particular easier to
// use safely and correctly, and ensuring nul-terminated results
// while being able to detect truncation.
//
// n is the full size of the destination buffer, including
// space for trailing nul, and including the pre-existing
// string for mystrlcat().  Thus can eg use sizeof(buffer),
// or exact size malloc-ed.
//
// Result is always nul-terminated, whether or not truncation occurs,
// and the return value is the strlen the destination would have had
// without truncation.  I.e., a return value >= input n indicates
// truncation occurred.
//
// Will assume that if configure found strlcpy/strlcat they are ok.
// For replacement implementations, will keep it simple rather
// than try for super-efficiency.
//
// Not sure about the asserts below, but they are easier than
// trying to ensure correct behaviour on strange inputs.
// In particular note that n==0 is prohibited (eg, since there
// must at least be room for a nul); could consider other options.
//***********************************************************************/
//size_t mystrlcpy(char *dest, final String src, size_t n)
//{
//  assert(dest != null);
//  assert(src != null);
//  assert(n>0);
//#ifdef HAVE_STRLCPY
//  return strlcpy(dest, src, n);
//#else
//  {
//    size_t len = src.length();
//    size_t num_to_copy = (len >= n) ? n-1 : len;
//    if (num_to_copy>0)
//      memcpy(dest, src, num_to_copy);
//    dest[num_to_copy] = '\0';
//    return len;
//  }
//#endif
//}
//
///**********************************************************************
// ...
//***********************************************************************/
//size_t mystrlcat(char *dest, final String src, size_t n)
//{
//  assert(dest != null);
//  assert(src != null);
//  assert(n>0);
//#ifdef HAVE_STRLCAT
//  return strlcat(dest, src, n);
//#else
//  {
//    size_t num_to_copy, len_dest, len_src;
//    
//    len_dest = dest.length();
//    assert(len_dest<n);
//    /* Otherwise have bad choice of leaving dest not nul-terminated
//     * within the specified length n (which should be assumable as
//     * a post-condition of mystrlcat), or modifying dest before end
//     * of existing string (which breaks strcat semantics).
//     */
//       
//    dest += len_dest;
//    n -= len_dest;
//    
//    len_src = src.length();
//    num_to_copy = (len_src >= n) ? n-1 : len_src;
//    if (num_to_copy>0)
//      memcpy(dest, src, num_to_copy);
//    dest[num_to_copy] = '\0';
//    return len_dest + len_src;
//  }
//#endif
//}
//
///**********************************************************************
// vsnprintf() replacement using a big malloc()ed internal buffer,
// originally by David Pfitzner <dwp@mso.anu.edu.au>
//
// Parameter n specifies the maximum number of characters to produce.
// This includes the trailing null, so n should be the actual number
// of characters allocated (or sizeof for char array).  If truncation
// occurs, the result will still be null-terminated.  (I'm not sure
// whether all native vsnprintf() functions null-terminate on
// truncation; this does so even if calls native function.)
//
// Return value: if there is no truncation, returns the number of
// characters printed, not including the trailing null.  If truncation
// does occur, returns the number of characters which would have been
// produced without truncation.
// (Linux man page says returns -1 on truncation, but glibc seems to
// do as above nevertheless; check_native_vsnprintf() above tests this.)
//
// [glibc is correct.  Viz.
//
// PRINTF(3)           Linux Programmer's Manual           PRINTF(3)
// 
// (Thus until glibc 2.0.6.  Since glibc 2.1 these functions follow the
// C99 standard and return the number of characters (excluding the
// trailing '\0') which would have been written to the final string if
// enough space had been available.)]
// 
// The method is simply to malloc (first time called) a big internal
// buffer, longer than any result is likely to be (for non-malicious
// usage), then vsprintf to that buffer, and copy the appropriate
// number of characters to the destination.  Thus, this is not 100%
// safe.  But somewhat safe, and at least safer than using raw snprintf!
// :-) (And of course if you have the native version it is safe.)
//
// Before rushing to provide a 100% safe replacement version, consider
// the following advantages of this method:
// 
// - It is very simple, so not likely to have many bugs (other than
// arguably the core design bug regarding absolute safety), nor need
// maintenance.
//
// - It uses native vsprintf() (which is required), thus exactly
// duplicates the native format-string parsing/conversions.
//
// - It is *very* portable.  Eg, it does not require mprotect(), nor
// does it do any of its own parsing of the format string, nor use
// any tricks to go through the va_list twice.
//
//***********************************************************************/
//
///* "64k should be big enough for anyone" ;-) */
//#define VSNP_BUF_SIZE (64*1024)
//int my_vsnprintf(char *str, size_t n, final String format, va_list ap)
//{
//  int r;
//
//  /* This may be overzealous, but I suspect any triggering of these to
//   * be bugs.  */
//
//  assert(str != null);
//  assert(n>0);
//  assert(format != null);
//
//#ifdef HAVE_WORKING_VSNPRINTF
//  r = vsnprintf(str, n, format, ap);
//  str[n - 1] = 0;
//
//  /* Convert C99 return value to C89.  */
//  if (r >= n)
//    return -1;
//
//  return r;
//#else
//  {
//    /* Don't use fc_malloc() or util.freelog() here, since they may call
//       my_vsnprintf() if it fails.  */
// 
//    static char *buf;
//    size_t len;
//
//    if (!buf) {
//      buf = malloc(VSNP_BUF_SIZE);
//
//      if (!buf) {
//	fprintf(stderr, "Could not allocate %i bytes for vsnprintf() " +
//		"replacement.", VSNP_BUF_SIZE);
//	exit(EXIT_FAILURE);
//      }
//    }
//#ifdef HAVE_VSNPRINTF
//    r = vsnprintf(buf, n, format, ap);
//#else
//    r = vsprintf(buf, format, ap);
//#endif
//    buf[VSNP_BUF_SIZE - 1] = '\0';
//    len = buf.length();
//
//    if (len >= VSNP_BUF_SIZE - 1) {
//      fprintf(stderr, "Overflow in vsnprintf replacement!" +
//              " (buffer size %d) aborting...\n", VSNP_BUF_SIZE);
//      abort();
//    }
//    if (n >= len + 1) {
//      memcpy(str, buf, len+1);
//      return len;
//    } else {
//      memcpy(str, buf, n-1);
//      str[n - 1] = '\0';
//      return -1;
//    }
//  }
//#endif  
//}
//
//int my_snprintf(char *str, size_t n, final String format)
//{
//  int ret;
//  va_list ap;
//
//  assert(format != null);
//  
//  va_start(ap, format);
//  ret = my_vsnprintf(str, n, format, ap);
//  va_end(ap);
//  return ret;
//}
//
///**********************************************************************
//  Call gethostname() if supported, else just returns -1.
//***********************************************************************/
//int my_gethostname(char *buf, size_t len)
//{
//#ifdef HAVE_GETHOSTNAME
//  return gethostname(buf, len);
//#else
//  return -1;
//#endif
//}
//
//#ifdef SOCKET_ZERO_ISNT_STDIN
///**********************************************************************
//  Support for console I/O in case SOCKET_ZERO_ISNT_STDIN.
//***********************************************************************/
//
//public static final int MYBUFSIZE = 100;
//static char mybuf[MYBUFSIZE+1];
//
///**********************************************************************/
//
//#ifdef WIN32_NATIVE
//static HANDLE mythread = INVALID_HANDLE_VALUE;
//
//static unsigned int WINAPI thread_proc(LPVOID data)
//{
//  if (fgets(mybuf, MYBUFSIZE, stdin)) {
//    char *s;
//    if ((s = strchr(mybuf, '\n')))
//      *s = '\0';
//  }
//  return 0;
//}
//#endif
//
///**********************************************************************
//  Initialize console I/O in case SOCKET_ZERO_ISNT_STDIN.
//***********************************************************************/
//void my_init_console()
//{
//#ifdef WIN32_NATIVE
//  unsigned int threadid;
//
//  if (mythread != INVALID_HANDLE_VALUE)
//    return;
//
//  mybuf[0] = '\0';
//  mythread = (HANDLE)_beginthreadex(null, 0, thread_proc, null, 0, &threadid);
//#else
//  static int initialized = 0;
//  if (!initialized) {
//    initialized = 1;
//#ifdef HAVE_FILENO
//    my_nonblock(fileno(stdin));
//#endif
//  }
//#endif
//}
//
///**********************************************************************
//  Read a line from console I/O in case SOCKET_ZERO_ISNT_STDIN.
//
//  This returns a pointer to a statically allocated buffer.
//  Subsequent calls to my_read_console() or my_init_console() will
//  overwrite it.
//***********************************************************************/
//char *my_read_console()
//{
//#ifdef WIN32_NATIVE
//  if (WaitForSingleObject(mythread, 0) == WAIT_OBJECT_0) {
//    CloseHandle(mythread);
//    mythread = INVALID_HANDLE_VALUE;
//    return mybuf;
//  }
//  return null;
//#else
//  if (!feof(stdin)) {    /* input from server operator */
//    static char *bufptr = mybuf;
//    /* fetch chars until \n, or run out of space in buffer */
//    /* blocks if my_nonblock() in my_init_console() failed */
//    while ((*bufptr = fgetc(stdin)) != EOF) {
//      if (*bufptr == '\n') *bufptr = '\0';
//      if (*bufptr == '\0') {
//	bufptr = mybuf;
//	return mybuf;
//      }
//      if ((bufptr - mybuf) <= MYBUFSIZE) bufptr++; /* prevent overrun */
//    }
//  }
//  return null;
//#endif
//}
//
//#endif
//
///**********************************************************************
//  Returns true iff the file is a regular file or a link to a regular
//  file or write_access is true and the file doesn't exists yet.
//***********************************************************************/
//boolean is_reg_file_for_access(final String name, boolean write_access)
//{
//  struct stat tmp;
//
//  if (stat(name, &tmp) == 0) {
//    return S_ISREG(tmp.st_mode);
//  } else {
//    return write_access && errno == ENOENT;
//  }
//}
//
///**********************************************************************
//  Character function wrappers
//
//  Some OS's (win32, Solaris) require a non-negative value as input
//  for these functions.
//***********************************************************************/
//
///**********************************************************************
//  Wrapper function to work around broken libc implementations.
//***********************************************************************/
//boolean my_isalnum(char c)
//{
//  return isalnum((int)((unsigned char)c)) != 0;
//}
//
///**********************************************************************
//  Wrapper function to work around broken libc implementations.
//***********************************************************************/
//boolean my_isalpha(char c)
//{
//  return isalpha((int)((unsigned char)c)) != 0;
//}
//
///**********************************************************************
//  Wrapper function to work around broken libc implementations.
//***********************************************************************/
//boolean my_isdigit(char c)
//{
//  return isdigit((int)((unsigned char)c)) != 0;
//}
//
///**********************************************************************
//  Wrapper function to work around broken libc implementations.
//***********************************************************************/
//boolean my_isprint(char c)
//{
//  return isprint((int)((unsigned char)c)) != 0;
//}
//
///**********************************************************************
//  Wrapper function to work around broken libc implementations.
//***********************************************************************/
//boolean my_isspace(char c)
//{
//  return isspace((int)((unsigned char)c)) != 0;
//}
//
///**********************************************************************
//  Wrapper function to work around broken libc implementations.
//***********************************************************************/
//boolean my_isupper(char c)
//{
//  return isupper((int)((unsigned char)c)) != 0;
//}
//
///**********************************************************************
//  Wrapper function to work around broken libc implementations.
//***********************************************************************/
//char my_toupper(char c)
//{
//  return (char) toupper((int)((unsigned char)c));
//}
//
///**********************************************************************
//  Wrapper function to work around broken libc implementations.
//***********************************************************************/
//char my_tolower(char c)
//{
//  return (char) tolower((int)((unsigned char)c));
//}
}